﻿using Abp.Authorization;
using Abp.Extensions;
using Abp.Linq.Expressions;
using Abp.UI;
using Basefr.App;
using Basefr.App.Helper;
using Basefr.Consts;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Paas.App.Interface.Meta;
using Paas.App.Interface.Meta.Dtos;
using Paas.App.Interface.Meta.Messages;
using Paas.Core;
using Paas.Core.Const.Enums;
using Paas.Core.Meta.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Paas.App.Meta
{
    [Route("meta-metaField")]

    [AbpAuthorize()]
    public class MetaFieldAppService : AppService, IMetaFieldAppService
    {
        /// <summary>
        /// 租户数据数据库连接字符串
        /// </summary>
        private readonly string customerConStr;
        private readonly IMainRepository<MetaField, Guid> _metaFieldRepo;
        private readonly IMainRepository<Application> _applicationRepo;
        private readonly IMainRepository<MetaObject, Guid> _metaObjectRepo;


        public MetaFieldAppService(IConfiguration configuration, IMainRepository<MetaField, Guid> metaFieldRepo,IMainRepository<Application> applicationRepo, IMainRepository<MetaObject, Guid> metaObjectRepo)
        {
            customerConStr=configuration[ConnectionStringNames.Customer];
            _metaFieldRepo = metaFieldRepo;
            _applicationRepo = applicationRepo;
            _metaObjectRepo = metaObjectRepo;
        }

        #region 增改
        [HttpPost(nameof(SaveMetaField))]
        public async Task<SaveMetaFieldOutput> SaveMetaField(SaveMetaFieldInput input)
        {
            if (input == null) throw new UserFriendlyException("保存字段信息失败：input为空！");
            if (string.IsNullOrWhiteSpace(input.Item.Name)) throw new UserFriendlyException("保存字段信息失败：Code为空！");

            var entity = ObjectMapper.Map<MetaField>(input.Item);
            if (input.Item?.Id != null && input.Item?.Id != Guid.Empty)
            {
                //var uData = await _metaFieldRepo.GetAsync(input.Item.Id);
                //if (uData == null) throw new UserFriendlyException("未找到需要更新的对象！");
                //uData.Description = input.Item.Description;
                await _metaFieldRepo.UpdateAsync(entity);
                return new SaveMetaFieldOutput();
            }

            Expression<Func<MetaField, bool>> predicate = p =>p.ObjectId==input.Item.ObjectId&&p.Name == input.Item.Name;
            var result = await _metaFieldRepo.GetAllListAsync(predicate);
            if (result.Count>0) throw new UserFriendlyException("保存字段信息失败：Code重复！请检查名称");

            //设置一些默认的值
            entity.MetaDataType??= MetaDataType.Custom;
            if (string.IsNullOrWhiteSpace(entity.MetaFieldGroup))
                entity.MetaFieldGroup = "default";
            entity.CurrentStatus ??= MetaStatus.New;

            await _metaFieldRepo.InsertAsync(entity);
            return new SaveMetaFieldOutput();
        }
        
        /// <summary>
        /// 发布字段
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost(nameof(PublicMetaField))]
        public async Task PublicMetaField(PublicMetaFieldInput input)
        {
            if (input!=null&&input?.Ids.Count>0)
            {
                foreach (var item in input.Ids)
                {
                    var uData = await _metaFieldRepo.GetAsync(item);
                    if (uData == null) throw new UserFriendlyException("未找到需要更新的对象！");
                    //首次发布时，创建Table
                    if (uData.CurrentStatus==MetaStatus.New)
                    {
                        // 获取应用名即是数据库名称
                        if (uData.ApplicationId==null) throw new UserFriendlyException($"{uData.Label}对象ApplicationId字段为Null！无法发布！");
                        var dataBaseName = _applicationRepo.FirstOrDefault((int)uData.ApplicationId)?.Name;
                        if (dataBaseName==null) throw new UserFriendlyException($"{uData.Label}对象未找到对应的应用！无法发布！");
                        // 获取对象名即是表名
                        if (uData.ObjectId==null) throw new UserFriendlyException($"{uData.Label}对象ObjectId字段为Null！无法发布！");
                        var tableName = _metaObjectRepo.FirstOrDefault(uData.ObjectId.To<Guid>())?.Name;
                        if (tableName==null) throw new UserFriendlyException($"{uData.Label}未找到对应的Object！无法发布！");
                        // 数据库添加字段
                        var conn = customerConStr+$"Initial Catalog={dataBaseName};";
                        var _sqlHelper = new SqlHelper(conn);
                        //获取sql数据库中的数据类型
                        var dataType = GetSqlDataType(uData.DataType);
                        _sqlHelper.AddColumn(tableName,uData.Name,dataType);

                        uData.CurrentStatus = MetaStatus.Released;
                        _metaFieldRepo.Update(uData);
                    }
                }
            }
        }
        #endregion

        #region 查
        [HttpPost(nameof(SearchMetaField))]
        public async Task<SearchMetaFieldOutput> SearchMetaField(SearchMetaFieldInput input)
        {
            Expression<Func<MetaField, bool>> predicate = p => true;
            if (!string.IsNullOrWhiteSpace(input.Name))
            {
                predicate = predicate.And(p => p.Name == input.Name);
            }
            if (!string.IsNullOrWhiteSpace(input.Label))
            {
                predicate = predicate.And(p => p.Label.Contains(input.Label.Trim()));
            }
            if (!string.IsNullOrWhiteSpace(input.ObjectId))
            {
                predicate = predicate.And(p => p.ObjectId == input.ObjectId);
            }
            if (input.CurrentStatus!=null&& input.CurrentStatus != 0)
            {
                predicate = predicate.And(p => p.CurrentStatus == input.CurrentStatus);
            }

            var result = await _metaFieldRepo.GetAllListAsync(predicate);
            var res = result.OrderByDescending(p => p.SortNum).Skip(input.SkipCount).Take(input.MaxResultCount).ToList();
            var totalCount = result.Count();
            var resultItems = ObjectMapper.Map<List<MetaFieldDto>>(res);
            return new SearchMetaFieldOutput { Items = resultItems, TotalCount = totalCount };
        }
        #endregion

        #region 删
        [HttpPost(nameof(DeleteMetaField))]
        public async Task<DeleteMetaFieldOutput> DeleteMetaField(DeleteMetaFieldInput input)
        {
            //await _metaFieldRepo.
            await _metaFieldRepo.DeleteAsync(input.Id);
            return new DeleteMetaFieldOutput();
        }
        #endregion

        /// <summary>
        /// 根据字段类型判断在sql数据库中对应的字段类型
        /// </summary>
        /// <param name="typeName"></param>
        /// <returns></returns>
        public string GetSqlDataType(DataType? typeName)
        {
            switch (typeName)
            {
                case DataType.Text:
                    return "varchar(50)";
                case DataType.DateTime:
                    return "datetime";
                case DataType.Boolean:
                    return "bit";
                case DataType.Int:
                    return "int";
                //case DataType.Long:
                //    return "varchar(50)";
                case DataType.Float:
                    return "float";
                case DataType.Double:
                    return "double";
                case DataType.Date:
                    return "date";
                case DataType.Enum:
                    return "int";
                case DataType.LongText:
                    return "nvarchar(MAX)";
                default:
                    throw new UserFriendlyException($"字段类型转换成Sql数据类型时出现错误！无法发布！");
            }
        }
    }
}
